<!DOCTYPE html>
<html>
  
<head><meta name="generator" content="Hexo 3.8.0">
  <meta charset="utf-8">
  <meta name="author" content="Amos Zhu">
  
  
  <title>类以及属性集按照规则过滤——一个简单的构建思路来解决 | Amos的技术博客</title>

  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  
    <meta name="keywords" content="stuff,stuff,数据过滤,">
  

  
  <meta name="description" content="近期在工作中遇到一个功能需求，基于类以及属性集的数据过滤，功能比较简单，但是的确花费了我一天的工作量来完成该功能，在开发这个功能过程中，我觉的有些问题的思考和处理方式觉得很有帮助，所以整理如下的博文，以便自己以后遇到类似的需求能快速的解决">

  

  
    <script src="//cdn.jsdelivr.net/npm/leancloud-storage@3.11.1/dist/av-min.js" async></script>
  

  
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML" async></script>
  

  
    <script src="//unpkg.com/valine/dist/Valine.min.js" async></script>
  

  

  <script>
  // theme-ad's config script
  // it can be used in every script
  
  window.AD_CONFIG = {
    leancloud: {"appid":"eObxCkTJ6j4GzRxGLgiHyfJa-gzGzoHsz","appkey":"fzRMAFC6MCE11mp7mnvh4Kwe","comment":true,"count":true},
    welcome: {"enable":true,"interval":30},
    start_time: "2019-05-28",
    passwords: ["efe07af7441da2b69c4a41e42e73be4db47f66010a56900788a458354a7373ec", ],
    is_post: true,
    lock: false,
    author: "Amos Zhu",
    share: {"qq":true,"wechat":true},
    mathjax: true,
    page_type: "",
    root: "/blog/"
  };
</script>

  <script src="/blog/vendor/sha256.min.js"></script>
<script src="/blog/js/auth.js"></script>
<script src="/blog/js/index.js"></script>
<script src="/blog/vendor/qrcode.min.js"></script>

  
    <link rel="icon" href="/blog/images/favicon.ico">
    <link rel="apple-touch-icon" href="/blog/images/touch-icon.png">
  

  <link href="//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">

  <link rel="stylesheet" href="/blog/css/index.css">
<link rel="stylesheet" href="/blog/styles/components/highlight/highlight.css">

  
</head>
  <body>
    <header class="site-header">
  <div class="site-header-brand">
    
      <span class="site-header-brand-title">
        <a href="/blog/">Amos Zhu</a>
      </span>
    
    
      <span class="site-header-brand-motto"> | 当浮躁的心静不下，不妨写些东西或者看会书</span>
    
  </div>
  <div class="site-header-right">
    <nav class="site-header-navigation">
      
        <a href="/blog/" target="_self">首页</a>
      
        <a href="/blog/archives/" target="_self">归档</a>
      
        <a href="/blog/tags/" target="_self">标签</a>
      
        <a href="/blog/categories/" target="_self">分类</a>
      
        <a href="/blog/redis/" target="_self">redis</a>
      
        <a href="/blog/rabbitMQ/" target="_self">rabbitMQ</a>
      
        <a href="/blog/elasticsearch" target="_self">elasticsearch</a>
      
        <a href="/blog/stuff" target="_self">stuff</a>
      
        <a href="/blog/kafka" target="_self">kafka</a>
      
        <a href="/blog/friends/" target="_self">友链</a>
      
        <a href="/blog/about/" target="_self">关于</a>
      
    </nav>
    <div class="site-header-btn">
      
        <a href="https://gitee.com/amos_zhu" target="_blank" id="site-github">
          <i class="fa fa-github-alt"></i>
        </a>
      
      <a href="javascript:void(0);" id="site-search">
        <i class="fa fa-search"></i>
      </a>
      <a href="javascript:void(0);" id="site-nav-btn">
        <i class="fa fa-ellipsis-v"></i>
      </a>
    </div>
  </div>
</header>
<nav class="table-content" id="site-nav">
  <div class="table-content-title">
    <span>导航</span>
  </div>
  <div class="table-content-main">
    <ol class="toc">
      
        <li class="toc-item">
          <a href="/blog/" target="_self">
            首页
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/archives/" target="_self">
            归档
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/tags/" target="_self">
            标签
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/categories/" target="_self">
            分类
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/redis/" target="_self">
            redis
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/rabbitMQ/" target="_self">
            rabbitMQ
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/elasticsearch" target="_self">
            elasticsearch
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/stuff" target="_self">
            stuff
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/kafka" target="_self">
            kafka
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/friends/" target="_self">
            友链
          </a>
        </li>
      
        <li class="toc-item">
          <a href="/blog/about/" target="_self">
            关于
          </a>
        </li>
      
    </ol>
  </div>
</nav>
<div id="site-process"></div>
    <main>
      
  <div class="passage">
  <div class="passage-meta">
    <span>
      <i class="fa fa-calendar"></i>2019-10-18
    </span>
    
      <span>
        | <a href="/blog/categories/stuff/"><i class="fa fa-bookmark"></i>stuff</a>
      </span>
    
    
      <span>
        | <i class="fa fa-unlock-alt"></i>UNLOCK
      </span>
    
  </div>
  <h1 class="passage-title">
    类以及属性集按照规则过滤——一个简单的构建思路来解决
  </h1>
  
  <article class="passage-article">
    <p></p>

<h3 id="需求如下："><a href="#需求如下：" class="headerlink" title="需求如下："></a>需求如下：</h3><blockquote>
<p>需要开发一个功能，能维护系统每个业务单据的数据项，每个业务单据的数据项是可以选择是否展示数据值，然后再系统展示的时候，根据已经维护好的数据项的单据，过滤其中不需要显示数据值的</p>
</blockquote>
<p>需求很简单，现在说明下代码结构：</p>
<ol>
<li>每个业务单据有DTO对象和Entity对象，其中DTO对象是显示给前端界面显示用的，Entity对象是单据对应的数据库模型</li>
<li>一个单据DTO对象可以有属性集List，表示父子级属性，Entity对象中不存在属性集</li>
<li>DTO对象和Entity对象属性名称相同（DTO比Entity多）</li>
</ol>
<h3 id="需求扩展说明："><a href="#需求扩展说明：" class="headerlink" title="需求扩展说明："></a>需求扩展说明：</h3><ol>
<li>根据需求，参数传递过来的是DTO对象，然后规则里面保存的Entity对象的属性全路径（包括属性集中的属性全路径）</li>
<li>需要根据Entity属性全路径的过滤规则来过滤DTO中的数据项的数据值</li>
<li>一个DTO对象可能含有多个属性集对象，属性集对象中的DTO也可能含有多个属性集对象</li>
</ol>
<h3 id="问题思考点："><a href="#问题思考点：" class="headerlink" title="问题思考点："></a>问题思考点：</h3><ol>
<li><p>因为传递的参数的DTO对象，而规则里面对应的都是Entity中的属性全路径，我们怎么去匹配他们之间的对应关系？</p>
<p> 我们需要建立一个映射关系，来获取DTO属性与Entity属性之间对应关系，这里需要注意的是DTO中有属性集List，映射关系也需要维护属性集的DTO和Entity对应的关系，</p>
<p> 我们在根据Entity过滤规则来过滤时，其实也就是根据映射关系中的DTO的属性全路径来过滤DTO中的对象（DTO的属性全路径和Entity属性全路径是不一致的，也有人会说直接根据属性字段来匹配，这里需要说明下，由于存在相同的基类，所以不同类的属性名称存在相同的，所以不能单据的根据属性名称来匹配，应该根据属性全路径来匹配）</p>
<p> <img src="https://s2.ax1x.com/2019/10/10/uo8nSJ.png" alt><br> 这里其实还有个问题，就是怎么知道DTO对应的Entity呢？方法很简单，我们可以通过自定义注解来解决，稍后在代码中我们会细细说明</p>
</li>
</ol>
<ol start="2">
<li><p>需要考虑到过滤的规则里面含有多个属性集的数据项过滤，如何才能过滤属性集中的数据项呢？</p>
<p> 这是个难点，我们来分析下，最顶级的是一个DTO对象，然后DTO对象中存在属性集，每个属性集对象中也可能含有属性集，这里我们需要建议一个模型结构：</p>
</li>
</ol>
<ul>
<li>该模型结构能知道当前的属性集对应的对象class信息，该class是为了能够知道该层级所有的属性字段，</li>
<li>模型结构需要存储当前节点的所有的属性集，为了迭代遍历</li>
<li>这个数据模型必须要符合树形节点结构，并且支持很好的遍历    </li>
<li>再添加我们的业务逻辑，每个节点的层级需要知道该层级中哪些字段属性是需要过滤的</li>
</ul>
<h3 id="开发代码逻辑："><a href="#开发代码逻辑：" class="headerlink" title="开发代码逻辑："></a>开发代码逻辑：</h3><p>分析了上述的模型结构，可以整理出一下的开发代码逻辑：</p>
<ol>
<li>我们需要获取DTO对象和Entity对象之间的映射关系</li>
<li>根据初始对象和过滤的规则字段，我们需要构建出模型结构</li>
<li>采用迭代的方式，循环遍历模型结构，依据当前节点的过滤属性来将该节点的数据项赋值为空</li>
<li>返回DTO对象</li>
</ol>
<h3 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h3><ol>
<li><p>首先我们先定义好自定义注解，为了获取DTO对象的Entity对象Class信息</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Copyright © 2018 五月工作室. All rights reserved.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Project</span>: stuff</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@ClassName</span>: AmMapping</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Package</span>: com.amos.stuff.filter.anno</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@author</span>: zhuqb</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Description</span>: DTO映射Entity对象</span></span><br><span class="line"><span class="comment">     * &lt;p&gt;</span></span><br><span class="line"><span class="comment">     * 该属性添加在类或者属性上，通过该注解可以知道DTO对应的Entity对象</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@date</span>: 2019/10/9 0009 下午 17:18</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Version</span>: V1.0</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Target</span>(&#123;ElementType.FIELD, ElementType.TYPE&#125;)</span><br><span class="line">    <span class="meta">@Retention</span>(RetentionPolicy.RUNTIME)</span><br><span class="line">    <span class="meta">@Documented</span></span><br><span class="line">    <span class="keyword">public</span> <span class="meta">@interface</span> AmMapping &#123;</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 当前DTO对象对应的Entity对象Class信息</span></span><br><span class="line"><span class="comment">         *</span></span><br><span class="line"><span class="comment">         * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        Class&lt;?&gt; entity();</span><br><span class="line">    &#125;</span><br><span class="line">```  </span><br><span class="line"><span class="number">2</span>. 定义好过滤的规则实体和基类</span><br><span class="line">```java</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Copyright © 2018 五月工作室. All rights reserved.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Project</span>: stuff</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@ClassName</span>: FilterRule</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Package</span>: com.amos.stuff.filter.bean</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@author</span>: zhuqb</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Description</span>: 过滤规则的对象</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@date</span>: 2019/10/9 0009 下午 17:23</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Version</span>: V1.0</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Data</span></span><br><span class="line">    <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">FilterRule</span> </span>&#123;</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * Entity对象属性全路径</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="keyword">private</span> String entityFieldFullName;</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 是否显示 true 是 false 否</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="keyword">private</span> Boolean show;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Copyright © 2018 五月工作室. All rights reserved.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Project</span>: stuff</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@ClassName</span>: BaseDTO</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Package</span>: com.amos.stuff.filter.bean</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@author</span>: zhuqb</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Description</span>: 数据模型的基类 这里作为泛型约束</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@date</span>: 2019/10/9 0009 下午 17:27</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@Version</span>: V1.0</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BaseDTO</span> </span>&#123;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>数据过滤处理器，代码中已经添加说明</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Copyright © 2018 五月工作室. All rights reserved.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Project</span>: stuff</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@ClassName</span>: DataFilterHandler</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Package</span>: com.amos.stuff.filter.handler</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: zhuqb</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span>: 数据过滤处理器</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span>: 2019/10/9 0009 下午 17:26</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Version</span>: V1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DataFilterHandler</span>&lt;<span class="title">T</span> <span class="keyword">extends</span> <span class="title">BaseDTO</span>&gt; </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">final</span> Logger logger = LoggerFactory.getLogger(<span class="keyword">this</span>.getClass());</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 属性全路径默认分隔符</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String DEFAULT_SPLIT_STR = <span class="string">"."</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> DEFAULT_MAP_LENGTH = <span class="number">100</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 泛型为 BaseDTO 的实体类对象</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> T dto;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 实体类对象的 Class</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> Class clazz;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * DTO中与Entity中字段的映射关系</span></span><br><span class="line"><span class="comment">     * Key 是DTO中的属性全称</span></span><br><span class="line"><span class="comment">     * Value 是Entity中与DTO匹配上的属性的全称</span></span><br><span class="line"><span class="comment">     * &lt;p&gt;</span></span><br><span class="line"><span class="comment">     * 该映射包括子集的属性列表</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> Map&lt;String, String&gt; mapping = <span class="keyword">new</span> ConcurrentHashMap&lt;&gt;(DEFAULT_MAP_LENGTH);</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 需要过滤的字段列表</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> List&lt;FilterRule&gt; filterList;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 模型结构</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> MockNode node = <span class="keyword">null</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 构造器初始化</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> dto</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> filterList</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">DataFilterHandler</span><span class="params">(T dto, List&lt;FilterRule&gt; filterList)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.dto = dto;</span><br><span class="line">        <span class="keyword">this</span>.clazz = dto.getClass();</span><br><span class="line">        <span class="keyword">this</span>.filterList = filterList;</span><br><span class="line">        <span class="comment">// 获取DTO与Entity之间的映射关系</span></span><br><span class="line">        <span class="keyword">this</span>.mapping();</span><br><span class="line">        <span class="keyword">this</span>.node = <span class="keyword">this</span>.initMockNode(<span class="keyword">null</span>, <span class="keyword">this</span>.clazz);</span><br><span class="line">        <span class="keyword">this</span>.logger.info(<span class="string">"组装之后的Node节点数据：&#123;&#125;"</span>, JSONObject.toJSONString(<span class="keyword">this</span>.node));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 初始化节点数据</span></span><br><span class="line"><span class="comment">     * &lt;p&gt;</span></span><br><span class="line"><span class="comment">     * 该方法主要是构建实体对象中的Node节点数据</span></span><br><span class="line"><span class="comment">     * 将实体类中含有需要过滤的属性集数据解析组装成固有数据结构的Node节点</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> pre 上一个节点的对象</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> cls 当前节点实体Class</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> MockNode <span class="title">initMockNode</span><span class="params">(MockNode pre, Class&lt;?&gt; cls)</span> </span>&#123;</span><br><span class="line">        MockNode node = <span class="keyword">new</span> MockNode();</span><br><span class="line">        <span class="comment">// 前一个节点 对于root节点来说，前一个节点为空</span></span><br><span class="line">        node.setPre(pre);</span><br><span class="line">        <span class="comment">// 本节点的class类型 对于属性集来说，class类型是属性集的泛型</span></span><br><span class="line">        <span class="comment">// 由于这里通过 注解 @RxPrintBean 来判断是否需要过滤的，需要属性集中的泛型对应的DTO对象也需要添加相应的注解</span></span><br><span class="line">        node.setClazz(cls);</span><br><span class="line">        <span class="comment">// 获取本节点对象的所有的Field</span></span><br><span class="line">        List&lt;Field&gt; fields = FieldUtils.getAllFieldsList(cls);</span><br><span class="line"></span><br><span class="line">        List&lt;MockNode&gt; nexts = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        List&lt;String&gt; noShowFields = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">        <span class="keyword">for</span> (Field field : fields) &#123;</span><br><span class="line">            field.setAccessible(Boolean.TRUE);</span><br><span class="line">            <span class="keyword">if</span> (field.getType().isAssignableFrom(List.class) &amp;&amp; field.isAnnotationPresent(AmMapping.class)) &#123;</span><br><span class="line">                <span class="keyword">this</span>.logger.info(<span class="string">"属性集Node:&#123;&#125;"</span>, field.getName());</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    Class&lt;?&gt; lClazz = ClassUtils.getFieldType(field);</span><br><span class="line">                    nexts.add(<span class="keyword">this</span>.initMockNode(node, lClazz));</span><br><span class="line">                &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">                    e.printStackTrace();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                <span class="comment">// 属性全称</span></span><br><span class="line">                String fieldName = cls.getName() + DEFAULT_SPLIT_STR + field.getName();</span><br><span class="line">                <span class="comment">// 如果 过滤列表中属性全称和 映射关系中的 Entity 属性全称相同</span></span><br><span class="line">                <span class="comment">// 并且 od是否发送为不发送</span></span><br><span class="line">                <span class="keyword">for</span> (FilterRule od : <span class="keyword">this</span>.filterList) &#123;</span><br><span class="line">                    <span class="keyword">for</span> (Map.Entry&lt;String, String&gt; entry : <span class="keyword">this</span>.mapping.entrySet()) &#123;</span><br><span class="line">                        <span class="keyword">if</span> (entry.getValue().equals(od.getEntityFieldFullName())</span><br><span class="line">                                &amp;&amp; !od.getShow()</span><br><span class="line">                                &amp;&amp; fieldName.equals(entry.getKey())) &#123;</span><br><span class="line">                            noShowFields.add(fieldName);</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        node.setNexts(nexts);</span><br><span class="line">        node.setNoShowFields(noShowFields);</span><br><span class="line">        <span class="keyword">return</span> node;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取映射关系</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">mapping</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">this</span>.logger.info(<span class="string">"开始组装DTO与Entity之间的映射关系"</span>);</span><br><span class="line">            <span class="keyword">this</span>.iteratorClass(<span class="keyword">this</span>.clazz);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(e.getMessage());</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 循环迭代生成DTO对象与Entity对象属性对应的映射关系</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> dtoClazz DTO 对象class</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">iteratorClass</span><span class="params">(Class dtoClazz)</span> </span>&#123;</span><br><span class="line">        <span class="comment">/**</span></span><br><span class="line"><span class="comment">         * 如果实体类中没有 RxPrintBean的注解 则直接返回</span></span><br><span class="line"><span class="comment">         */</span></span><br><span class="line">        <span class="keyword">if</span> (!<span class="keyword">this</span>.clazz.isAnnotationPresent(AmMapping.class)) &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 获取类上的 RxPrintBean 的注解</span></span><br><span class="line">        AmMapping rpb = AnnotationUtils.findAnnotation(dtoClazz, AmMapping.class);</span><br><span class="line">        <span class="keyword">if</span> (StringUtils.isEmpty(rpb)) &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(dtoClazz.getName() + <span class="string">"需要添加注解:@AmMapping"</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        Class cls = rpb.entity();</span><br><span class="line">        <span class="comment">// 获取注解值 指定类的 Field 属性列表</span></span><br><span class="line">        List&lt;Field&gt; srcList = FieldUtils.getAllFieldsList(cls);</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 获取目标的属性列表</span></span><br><span class="line">        List&lt;Field&gt; destList = FieldUtils.getAllFieldsList(dtoClazz);</span><br><span class="line">        <span class="keyword">for</span> (Field field : destList) &#123;</span><br><span class="line">            Boolean accessible = field.isAccessible();</span><br><span class="line">            field.setAccessible(Boolean.TRUE);</span><br><span class="line">            <span class="comment">// 循环生成属性列表</span></span><br><span class="line">            <span class="keyword">if</span> (field.getType().isAssignableFrom(List.class)) &#123;</span><br><span class="line">                <span class="keyword">if</span> (field.isAnnotationPresent(AmMapping.class)) &#123;</span><br><span class="line">                    <span class="comment">// 属性集的泛型</span></span><br><span class="line">                    Class&lt;?&gt; lClazz = ClassUtils.getFieldType(field);</span><br><span class="line">                    <span class="keyword">if</span> (!StringUtils.isEmpty(lClazz)) &#123;</span><br><span class="line">                        <span class="keyword">this</span>.logger.info(<span class="string">"实体中的集合：&#123;&#125;"</span>, lClazz);</span><br><span class="line">                        <span class="keyword">this</span>.iteratorClass(lClazz);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"></span><br><span class="line">                <span class="comment">// 生成DTO与Entity之间的映射关系</span></span><br><span class="line">                <span class="keyword">for</span> (Field srcField : srcList) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (srcField.getName().equals(field.getName())) &#123;</span><br><span class="line">                        <span class="keyword">this</span>.mapping.put(dtoClazz.getName() + DEFAULT_SPLIT_STR + field.getName(), cls.getName() + DEFAULT_SPLIT_STR + srcField.getName());</span><br><span class="line">                        <span class="keyword">continue</span>;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">            &#125;</span><br><span class="line">            field.setAccessible(accessible);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 过滤数据项的方法</span></span><br><span class="line"><span class="comment">     * 1. 先过滤父类的数据，然后迭代过滤属性集中的数据</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> T <span class="title">filter</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">// 如果没有过滤的字段 ，则全部返回</span></span><br><span class="line">        <span class="keyword">if</span> (CollectionUtils.isEmpty(<span class="keyword">this</span>.filterList)) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="keyword">this</span>.dto;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">this</span>.logger.info(<span class="string">"过滤之前的数据:&#123;&#125;"</span>, JSONObject.toJSONString(<span class="keyword">this</span>.dto));</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">this</span>.filterData(<span class="keyword">this</span>.dto, <span class="keyword">this</span>.node.getNoShowFields());</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> RuntimeException(e.getMessage());</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="keyword">this</span>.mapping.clear();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">this</span>.logger.info(<span class="string">"过滤之后的数据:&#123;&#125;"</span>, JSONObject.toJSONString(<span class="keyword">this</span>.dto));</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.dto;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 过滤数据，主要用来过滤父级的数据，在父级属性过滤的过程中，过滤属性集中的数据</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> dto              DTO 对象</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> nowShowFieldList 不需要展示的DTO属性列表</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> Exception</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">filterData</span><span class="params">(T dto, List&lt;String&gt; nowShowFieldList)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            Class&lt;?&gt; dtoClass = dto.getClass();</span><br><span class="line"></span><br><span class="line">            List&lt;Field&gt; fields = FieldUtils.getAllFieldsList(dtoClass);</span><br><span class="line">            String fieldName = <span class="keyword">null</span>;</span><br><span class="line">            <span class="keyword">for</span> (Field field : fields) &#123;</span><br><span class="line">                field.setAccessible(Boolean.TRUE);</span><br><span class="line">                fieldName = dtoClass.getName() + DEFAULT_SPLIT_STR + field.getName();</span><br><span class="line">                <span class="keyword">if</span> (nowShowFieldList.contains(fieldName)) &#123;</span><br><span class="line"></span><br><span class="line">                    field.set(dto, <span class="keyword">null</span>);</span><br><span class="line">                &#125;</span><br><span class="line">                <span class="keyword">if</span> (field.getType().isAssignableFrom(List.class) &amp;&amp; field.isAnnotationPresent(AmMapping.class)) &#123;</span><br><span class="line">                    List&lt;T&gt; list = (List&lt;T&gt;) field.get(dto);</span><br><span class="line">                    <span class="keyword">this</span>.filterData(<span class="keyword">this</span>.node, list);</span><br><span class="line">                    field.set(dto, list);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IllegalAccessException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 迭代循环过滤数据，主要是用来过滤属性集中的数据</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> umn  Node节点数据</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> list 属性集数据</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> Exception</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">filterData</span><span class="params">(MockNode umn, List&lt;T&gt; list)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        <span class="comment">// 获取下级节点，如果没有下级节点就返回</span></span><br><span class="line">        List&lt;MockNode&gt; nexts = umn.getNexts();</span><br><span class="line">        <span class="keyword">if</span> (CollectionUtils.isEmpty(nexts)) &#123;</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        Class&lt;?&gt; cls = <span class="keyword">null</span>;</span><br><span class="line">        <span class="comment">// 这里的处理步骤，循环每个属性节点</span></span><br><span class="line">        <span class="comment">// 将每条记录信息里面的所有的属性字段遍历</span></span><br><span class="line">        <span class="comment">// 如果该属性字段是不需要显示值的，则将该属性的值置为空</span></span><br><span class="line">        <span class="comment">// 查看本级属性有没有是属性集的，如果有的话，则循环迭代继续重复上述的步骤来过滤数据</span></span><br><span class="line">        <span class="keyword">for</span> (MockNode mockNode : nexts) &#123;</span><br><span class="line">            cls = mockNode.getClazz();</span><br><span class="line">            <span class="keyword">this</span>.logger.info(<span class="string">"当前节点的Class信息:&#123;&#125;"</span>, cls);</span><br><span class="line">            <span class="comment">// 获取本级不需要显示的字段信息</span></span><br><span class="line">            List&lt;String&gt; noShowFields = mockNode.getNoShowFields();</span><br><span class="line">            <span class="comment">// 获取本级所有的属性字段信息</span></span><br><span class="line">            List&lt;Field&gt; fields = FieldUtils.getAllFieldsList(cls);</span><br><span class="line">            String fieldName = <span class="keyword">null</span>;</span><br><span class="line">            <span class="keyword">for</span> (T t : list) &#123;</span><br><span class="line">                <span class="keyword">for</span> (Field field : fields) &#123;</span><br><span class="line">                    fieldName = cls.getName() + DEFAULT_SPLIT_STR + field.getName();</span><br><span class="line">                    <span class="keyword">if</span> (noShowFields.contains(fieldName)) &#123;</span><br><span class="line">                        field.setAccessible(Boolean.TRUE);</span><br><span class="line"></span><br><span class="line">                        field.set(t, <span class="keyword">null</span>);</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">if</span> (field.getType().isAssignableFrom(List.class) &amp;&amp; field.isAnnotationPresent(AmMapping.class)) &#123;</span><br><span class="line">                        List&lt;T&gt; data = (List&lt;T&gt;) field.get(t);</span><br><span class="line">                        <span class="keyword">this</span>.filterData(mockNode, data);</span><br><span class="line">                        <span class="comment">// 过滤后的数据需要重新赋值到原来的属性中</span></span><br><span class="line">                        field.set(t, data);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
</ol>
<p>核心的代码我一次性贴了出来，代码不是很难，主要是根据上面的分析的思路来编写代码的，一些比较晦涩的地方，我也都添加详细的注释了，具体的代码可以查看我的Gitee项目：<a href="https://gitee.com/amos_zhu/stuff" target="_blank" rel="noopener">stuff</a></p>
<h3 id="测试用例"><a href="#测试用例" class="headerlink" title="测试用例"></a>测试用例</h3><p>上述核心的代码已经实现了，接下来我们来编写测试用例来看看我们的代码功能是否正常:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Copyright © 2018 五月工作室. All rights reserved.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Project</span>: stuff</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@ClassName</span>: BizDetailEntity</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Package</span>: com.amos.stuff.filter.bean.entity</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: zhuqb</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span>:</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span>: 2019/10/10 0010 上午 8:13</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Version</span>: V1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BizDetailEntity</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String company;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Date startTime;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Integer quantum;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String experience;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Copyright © 2018 五月工作室. All rights reserved.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Project</span>: stuff</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@ClassName</span>: BizEntity</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Package</span>: com.amos.stuff.filter.bean.entity</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: zhuqb</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span>:</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span>: 2019/10/10 0010 上午 8:09</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Version</span>: V1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BizEntity</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> String email;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line">    <span class="keyword">private</span> String grade;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Copyright © 2018 五月工作室. All rights reserved.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Project</span>: stuff</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@ClassName</span>: BizDetailDTO</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Package</span>: com.amos.stuff.filter.bean</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: zhuqb</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span>:</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span>: 2019/10/9 0009 下午 18:00</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Version</span>: V1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@AmMapping</span>(entity = BizDetailEntity.class)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BizDetailDTO</span> <span class="keyword">extends</span> <span class="title">BaseDTO</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String company;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Date startTime;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> Integer quantum;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String experience;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Copyright © 2018 五月工作室. All rights reserved.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Project</span>: stuff</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@ClassName</span>: BizDTO</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Package</span>: com.amos.stuff.filter.bean</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: zhuqb</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span>:</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span>: 2019/10/9 0009 下午 17:58</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Version</span>: V1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@AmMapping</span>(entity = BizEntity.class)</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">BizDTO</span> <span class="keyword">extends</span> <span class="title">BaseDTO</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> String email;</span><br><span class="line">    <span class="keyword">private</span> Integer age;</span><br><span class="line">    <span class="keyword">private</span> String grade;</span><br><span class="line">    <span class="meta">@AmMapping</span>(entity = BizDetailEntity.class)</span><br><span class="line">    <span class="keyword">private</span> List&lt;BizDetailDTO&gt; bizDetails;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Copyright © 2018 五月工作室. All rights reserved.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Project</span>: stuff</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@ClassName</span>: MockData</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Package</span>: com.amos.stuff.filter.mock</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: zhuqb</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span>: 组装模拟数据</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span>: 2019/10/10 0010 上午 8:16</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Version</span>: V1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MockData</span> </span>&#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 模拟DTO数据对象</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> BizDTO <span class="title">mockBiz</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        String mockStr = <span class="string">"&#123;\n"</span> +</span><br><span class="line">                <span class="string">"  \"name\": \"amos\",\n"</span> +</span><br><span class="line">                <span class="string">"  \"email\": \"amoszhu@aliyun.com\",\n"</span> +</span><br><span class="line">                <span class="string">"  \"age\": 30,\n"</span> +</span><br><span class="line">                <span class="string">"  \"grade\": \"6\",\n"</span> +</span><br><span class="line">                <span class="string">"  \"bizDetails\": [\n"</span> +</span><br><span class="line">                <span class="string">"    &#123;\n"</span> +</span><br><span class="line">                <span class="string">"      \"company\": \"xxx公司1\",\n"</span> +</span><br><span class="line">                <span class="string">"      \"startTime\": 1570666889755,\n"</span> +</span><br><span class="line">                <span class="string">"      \"quantum\": 2,\n"</span> +</span><br><span class="line">                <span class="string">"      \"experience\": \"能吃苦耐劳\"\n"</span> +</span><br><span class="line">                <span class="string">"    &#125;,\n"</span> +</span><br><span class="line">                <span class="string">"    &#123;\n"</span> +</span><br><span class="line">                <span class="string">"      \"company\": \"xxx公司2\",\n"</span> +</span><br><span class="line">                <span class="string">"      \"startTime\": 1570666899755,\n"</span> +</span><br><span class="line">                <span class="string">"      \"quantum\": 2,\n"</span> +</span><br><span class="line">                <span class="string">"      \"experience\": \"能吃苦耐劳\"\n"</span> +</span><br><span class="line">                <span class="string">"    &#125;\n"</span> +</span><br><span class="line">                <span class="string">"  ]\n"</span> +</span><br><span class="line">                <span class="string">"&#125;"</span>;</span><br><span class="line">        BizDTO bizDTO = JSONObject.parseObject(mockStr, BizDTO.class);</span><br><span class="line">        <span class="keyword">return</span> bizDTO;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 模拟数据过滤规则</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> List&lt;FilterRule&gt; <span class="title">mockRule</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        String mockStr = <span class="string">"[\n"</span> +</span><br><span class="line">                <span class="string">"  &#123;\n"</span> +</span><br><span class="line">                <span class="string">"    \"entityFieldFullName\":\"com.amos.stuff.filter.bean.entity.BizEntity.name\",\n"</span> +</span><br><span class="line">                <span class="string">"    \"show\":false\n"</span> +</span><br><span class="line">                <span class="string">"  &#125;,\n"</span> +</span><br><span class="line">                <span class="string">"  &#123;\n"</span> +</span><br><span class="line">                <span class="string">"    \"entityFieldFullName\":\"com.amos.stuff.filter.bean.entity.BizDetailEntity.experience\",\n"</span> +</span><br><span class="line">                <span class="string">"    \"show\":false\n"</span> +</span><br><span class="line">                <span class="string">"  &#125;\n"</span> +</span><br><span class="line">                <span class="string">"]"</span>;</span><br><span class="line">        List&lt;FilterRule&gt; list = JSONArray.parseArray(mockStr, FilterRule.class);</span><br><span class="line">        <span class="keyword">return</span> list;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>模拟测试数据<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Copyright © 2018 五月工作室. All rights reserved.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Project</span>: stuff</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@ClassName</span>: DataFilterTest</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Package</span>: com.amos.stuff.filter</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: zhuqb</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span>:</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@date</span>: 2019/10/9 0009 下午 17:53</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Version</span>: V1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@RunWith</span>(SpringRunner.class)</span><br><span class="line"><span class="meta">@SpringBootTest</span>(classes = &#123;StuffApplication.class&#125;)<span class="comment">// 指定启动类</span></span><br><span class="line"><span class="meta">@Slf</span>4j</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">DataFilterTest</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">testFilter</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        MockData data = <span class="keyword">new</span> MockData();</span><br><span class="line">        BizDTO dto = data.mockBiz();</span><br><span class="line">        List&lt;FilterRule&gt; filterList = data.mockRule();</span><br><span class="line"></span><br><span class="line">        DataFilterHandler handler = <span class="keyword">new</span> DataFilterHandler(dto, filterList);</span><br><span class="line">        handler.filter();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>执行该段代码，查看运行的日志，看看是否数据是否已经过滤</p>
<p><img src="https://s2.ax1x.com/2019/10/10/uo1GB6.png" alt></p>
<p>从上面的运行日志我们可以看出，我们之前模拟的过滤父类属性全路径中的name属性和子类属性全路径中的experience属性，在过滤后的数据中已经没有了，目前来说功能还是正常的。</p>
<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>上述代码的中心思想是构建一个类似树形结构的节点数据，然后解析类的结构，按照树形结构的特点来初始化该类的树形结构，同时整合业务需要过滤的字段，这样做的好处是为接下来的类的层级遍历提供的方便，并且过滤数据时，只需要考虑本节点的属性过滤即可</p>
<p>将原来复杂的多层级的结构数据过滤换元成单层级的数据过滤，这样处理起来了就方便多了，唯一要注意的地方是过滤完成之后的数据需要重新复制到当前层级的对象中</p>
<p>接入方法如下：</p>
<ol>
<li>需要过滤的DTO对象添加自定义注解 <code>@AmMapping</code>, 同时对象中的属性集也需要添加该自定义注解，注解的值是对应的Entity类</li>
<li>定义好数据过滤的规则，然后调用处理器来处理即可</li>
</ol>
<p>总的来说，接入还是非常简单的，只需要在需要过滤的DTO对象中添加自定义注解，维护好DTO与Entity之间的属性对应关系即可    </p>
  </article>
  <aside class="table-content" id="site-toc">
  <div class="table-content-title">
    <i class="fa fa-arrow-right fa-lg" id="site-toc-hide-btn"></i>
    <span>目录</span>
  </div>
  <div class="table-content-main">
    <ol class="toc"><li class="toc-item toc-level-3"><a class="toc-link" href="#需求如下："><span class="toc-text">需求如下：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#需求扩展说明："><span class="toc-text">需求扩展说明：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#问题思考点："><span class="toc-text">问题思考点：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#开发代码逻辑："><span class="toc-text">开发代码逻辑：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#代码实现"><span class="toc-text">代码实现</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#测试用例"><span class="toc-text">测试用例</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#总结"><span class="toc-text">总结</span></a></li></ol>
  </div>
</aside>
  
    <aside class="passage-copyright">
      <div>本文作者: Amos Zhu</div>
      
        <div>
          原文链接: 
          <a href target="_blank">http://amos_zhu.gitee.io/passages/类以及属性集按照规则过滤——一个简单的构建思路来解决/</a>
        </div>
      
      <div>
        版权声明: 本博客所有文章除特别声明外, 均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a> 许可协议. 转载请注明出处!
      </div>
    </aside>
  
  
    <div class="passage-tags">
     
      <a href="/blog/tags/stuff/"><i class="fa fa-tags"></i>stuff</a>
     
      <a href="/blog/tags/数据过滤/"><i class="fa fa-tags"></i>数据过滤</a>
    
    </div>
  
</div>

    </main>
    
      
<div class="site-comment-contanier" data-plateform="leancloud">
  
    <p id="site-comment-info">
      <i class="fa fa-spinner fa-spin"></i> 评论加载中
    </p>
    <div id="site-comment"></div>
  
</div>
    
    <div class="site-footer-wrapper">
  <footer class="site-footer">
    
      
        <div class="site-footer-col">
          <h5 class="site-footer-title">博客推荐</h5>
          
            <span class="site-footer-item">
              <a href="http://youzhixueyuan.com/series/java" target="_blank">优知学院</a>
            </span>
          
            <span class="site-footer-item">
              <a href="http://ruanyifeng.com/" target="_blank">阮一峰的个人网站</a>
            </span>
          
        </div>
      
        <div class="site-footer-col">
          <h5 class="site-footer-title">系列教程</h5>
          
            <span class="site-footer-item">
              <a href="http://amos_zhu.gitee.io/blog/redis" target="_blank">Redis系列教程</a>
            </span>
          
            <span class="site-footer-item">
              <a href="http://amos_zhu.gitee.io/blog/rabbitMQ/" target="_blank">RabbitMQ教程</a>
            </span>
          
            <span class="site-footer-item">
              <a href="http://amos_zhu.gitee.io/blog/kafka/" target="_blank">Kafka架构探险</a>
            </span>
          
        </div>
      
        <div class="site-footer-col">
          <h5 class="site-footer-title">抓到我</h5>
          
            <span class="site-footer-item">
              <a href="https://gitee.com/amos_zhu" target="_blank">Gitee</a>
            </span>
          
            <span class="site-footer-item">
              <a href="https://blog.csdn.net/wdcl2468" target="_blank">CSDN</a>
            </span>
          
            <span class="site-footer-item">
              <a href="https://www.jianshu.com/u/2dbe61b1f3c3" target="_blank">简书</a>
            </span>
          
        </div>
      
    
    <div class="site-footer-info">
      <i class="fa fa-clock-o"></i> 本站已稳定运行<span id="site-time"></span>
    </div>
    
      <div class="site-footer-info">
        <i class="fa fa-paw"></i> 您是本站第 <span id="site-count"></span> 位访客
      </div>
    
    
      <div class="site-footer-info">
        <i class="fa fa-at"></i> Email: amoszhu@aliyun.com
      </div>
    
    <div class="site-footer-info">
      <i class="fa fa-copyright"></i> 
      2019 <a href="https://github.com/dongyuanxin/theme-ad/" target="_blank">Theme-AD</a>.
      Created by <a href="https://godbmw.com/" target="_blank">GodBMW</a>.
      All rights reserved.
    </div>
  </footer>
</div>
    <div id="site-layer" style="display:none;">
  <div class="site-layer-content">
    <div class="site-layer-header">
      <span class="site-layer-header-title" id="site-layer-title"></span>
      <i class="fa fa-close" id="site-layer-close"></i>
    </div>
    <div class="site-layer-body" id="site-layer-container">
      <div class="site-layer-input" id="site-layer-search" style="display: none;">
        <div class="site-layer-input-choose">
          <a href="javascript:void(0);" title="Change Search Engine">Google</a>
        </div>
        <input type="text">
        <i class="fa fa-search"></i>
      </div>
      
        <div class="site-layer-reward" id="site-layer-reward" style="display: none;">
          
            <div>
              <img src="/blog/images/wechat.png" alt="WeChat">
              
                <p>WeChat</p>
              
            </div>
          
            <div>
              <img src="/blog/images/alipay.png" alt="AliPay">
              
                <p>AliPay</p>
              
            </div>
          
        </div>
      
      <div id="site-layer-welcome" style="display:none;"></div>
    </div>
  </div>
</div>
    

<div class="bottom-bar">
  <div class="bottom-bar-left">
    <a href="/blog/passages/Kafka架构探险（二）——一文带你了解Kafka/" data-enable="true">
      <i class="fa fa-arrow-left"></i>
    </a>
    <a href="/blog/passages/策略模式-Spring——让我们的代码更加高大上一点/" data-enable="true">
      <i class="fa fa-arrow-right"></i>
    </a>
  </div>
  <div class="bottom-bar-right">
    <a href="javascript:void(0);" data-enable="true" id="site-toc-show-btn">
      <i class="fa fa-bars"></i>
    </a>
    
      <a href="#site-comment" data-enable="true">
        <i class="fa fa-commenting"></i>
      </a>
    
    <a href="javascript:void(0);" id="site-toggle-share-btn">
      <i class="fa fa-share-alt"></i>
    </a>
    
      <a href="javascript:void(0);" id="site-reward">
        <i class="fa fa-thumbs-up"></i>
      </a>
    
    <a href="javascript:void(0);" id="back-top-btn">
      <i class="fa fa-chevron-up"></i>
    </a>
  </div>
</div>
    <div id="share-btn">
  
  
  
  
    <a id="share-btn-qq" href="javascript:void(0);" target="_blank">
      <i class="fa fa-qq"></i>
    </a>
  
  
    <a id="share-btn-wechat" href="javascript:void(0);" target="_blank">
      <i class="fa fa-wechat"></i>
    </a>
  
</div>
    


  <script async>
  (function(){
      var bp = document.createElement('script');
      var curProtocol = window.location.protocol.split(':')[0];
      if (curProtocol === 'https') {
          bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
      }
      else {
          bp.src = 'http://push.zhanzhang.baidu.com/push.js';
      }
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(bp, s);
  })();
  </script>



  <script async>
    (function(){
    var src = (document.location.protocol == "http:") ? "http://js.passport.qihucdn.com/11.0.1.js?":"https://jspassport.ssl.qhimg.com/11.0.1.js?";
    document.write('<script src="' + src + '" id="sozz"><\/script>');
    })();
  </script>


    
  </body>
</html>